import DatabaseUtils from "../utils/db-utils";
import {BATTLE, BOOLEAN, PAGE_STATUS, USER_STATUS} from "../configs/config";
import FileUtils from "../utils/file-utils";

const fileUtils = new FileUtils();

class UserStateDao {

    /**
     * 查询用户状态表
     * @param where 条件：[['userId', '123'], [column, value]] <为空时不指定条件>
     */
    static queryUserStateTable = async (where: any[]) => {
        const tableName = 't_user_state';
        const columns = ['id', 'user_id', 'token', 'disconnect_time', 'user_page', 'is_room_admin', 'room_id', 'first',
            'join_type', 'room_status', 'is_ready', 'battle_id', 'user_status', 'create_time', 'update_time'];
        const sqlObj = DatabaseUtils.getDynamicSelectObj(tableName, columns, where);
        return await DatabaseUtils.execSql(sqlObj.sql, sqlObj.params);
    };

    /**
     * 动态更新用户游离表
     * @param columns
     * @param where
     * @returns {Promise<unknown>}
     */
    static updateUserStateTable = async (columns: any[], where: any[]) => {
        const tableName = 't_user_state';
        const sqlObj = DatabaseUtils.getDynamicUpdateObj(tableName, columns, where);
        return await DatabaseUtils.execSql(sqlObj.sql, sqlObj.params);
    };

    /**
     * 删除游离表中的用户
     * @param userId
     * @returns {Promise<boolean>}
     */
    static deleteUserState = async (userId: string) => {
        const sql = `delete from t_user_state where user_id = ?`;
        const params = [userId];
        await DatabaseUtils.execSql(sql, params);
        return true;
    };

    /**
     * 查询数据库的房间信息
     * @param userId
     * @param historyRoomIds 历史加入过的房间列表
     * @param roomStatus
     */
    static queryValidRooms = async (userId: string, historyRoomIds: string[], roomStatus: string) => {
        const roomIdNotInValue = historyRoomIds.length ? historyRoomIds.join(',') : '0';
        const sql = `select b.room_id as roomId, b.lock_pass as lockPass, b.is_room_admin as isRoomAdmin
                 from t_user_state b left join t_user a on a.user_id = b.user_id
              where b.user_id <> ? 
              and b.room_status = ? 
              and b.room_id not in (${roomIdNotInValue})
              and b.room_id is not null 
              and b.lock_pass is null
              and (select count(*) from t_user_state a where a.room_id = b.room_id and a.user_status <> ?) < 2`;
        const params = [userId, roomStatus, USER_STATUS.WATCH];
        return await DatabaseUtils.execSql(sql, params);
    };

    /**
     * 查询已断开服务器超过指定时长的数据
     * @param disconnectTimeSeconds
     * @returns {Promise<void>}
     */
    static getDisconnectTimeUser = async (disconnectTimeSeconds: number) => {
        const sql = `select user_id as userId, room_id as roomId from t_user_state where TIMESTAMPDIFF(second, disconnect_time, now()) >= ?`;
        const params = [disconnectTimeSeconds];
        return await DatabaseUtils.execSql(sql, params);
    };

    /**
     * 更新求和状态
     * @param userId
     * @param status
     * @param sendUserId 发起人
     * @return {Promise<boolean>}
     */
    static updateBattlePeace = async (userId: string, status: string, sendUserId: string | null) => {
        const userStateSql = `select battle_id as battleId from t_user_state where user_id = ?`;
        const userStateParams = [userId];
        const userStateRows: any = await DatabaseUtils.execSql(userStateSql, userStateParams);
        if (!userStateRows || userStateRows.length === 0) {
            return false;
        } else {
            const [userState] = userStateRows;
            const battleId = userState.battleId;

            const sql = `update t_battle set send_peace = ?, send_user_id = ? where id = ? `;
            const params = [status, sendUserId, battleId];
            const rows: any = await DatabaseUtils.execSql(sql, params);
            return rows.length === 0;
        }
    }

    /**
     * 查询在线人数
     * 统计条件：在房间中等待的用户
     */
    static queryOnlineCount = async () => {
        const sql = `select count(*) as total from t_user_state 
                      where room_status is not null
                        and (user_status is null or user_status <> ?)`;
        const rows: any = await DatabaseUtils.execSql(sql, [USER_STATUS.WATCH]);
        return rows.length == 0 ? 0 : rows[0].total;
    }

    /**
     * 观战数据查询
     * @param userId
     * @param roomId
     */
    static queryWatchList = async (userId: string, roomId: string) => {
        const sql = `select a.user_id as userId, b.user_name as userName from t_user_state a 
                  left join t_user b on a.user_id = b.user_id where a.room_id = ? and a.user_status = ?`;
        const params = [roomId, USER_STATUS.WATCH];
        return await DatabaseUtils.execSql(sql, params);
    }

    /**
     * 查询桌子数据
     * @param userId
     * @param pageNum
     * @param pageSize
     */
    static getRoomListByPage = async (userId: string, pageNum: number, pageSize: number) => {
        const dataTotal = BATTLE.MAX_ROOM;
        // 新房间数据
        const beginRoomId = (pageNum - 1) * pageSize + 1;
        const endRoomId = Math.min(pageNum * pageSize, dataTotal);
        const list: any = [];
        for(let roomId = beginRoomId; roomId <= endRoomId; ++roomId) {
            let user = null, enemy = null;
            const sql = `select a.first          as first,
                                    b.pk_total_count as pkTotalCount,
                                    b.pk_win_count   as pkWinCount,
                                    b.score          as score,
                                    a.is_ready       as isReady,
                                    a.room_id        as roomId,
                                    b.user_id        as userId,
                                    b.user_name      as userName,
                                    b.icon_url       as iconUrl,
                                    a.room_status    as roomStatus,
                                    a.is_room_admin  as isRoomAdmin
                              from t_user_state a
                              left join t_user b on a.user_id = b.user_id
                             where a.room_id = ?
                               and a.room_status is not null
                               and (a.user_status is null or a.user_status <> ?)`;
            const userStateRows: any = await DatabaseUtils.execSql(sql, [roomId, USER_STATUS.WATCH]);
            if(userStateRows.length !== 0) {
                // 获取双方数据
                user = userStateRows.find((user: any) => user.first);
                enemy = userStateRows.find((user: any) => !user.first);
                // 对图片进行转义
                user && (user.iconUrl = fileUtils.getShowPath(user.iconUrl));
                enemy && (enemy.iconUrl = fileUtils.getShowPath(enemy.iconUrl));
            }
            list.push({ roomId: roomId, user: user, enemy: enemy });
        }
        return {dataTotal: dataTotal, list: list};
    }

    /**
     * 根据用户Id查询游离数据
     * @param userId
     */
    static getUserStateByUserId = async (userId: string) => {
        const sql = `select id, user_id as userId, disconnect_time as disconnectTime, user_page as userPage, room_id as roomId, 
                        join_type as joinType, token, first, room_status as roomStatus, is_ready as isReady, battle_id as battleId, 
                        user_status as userStatus,  is_room_admin as isRoomAdmin, lock_pass as lockPass 
                    from t_user_state where user_id = ?`;
        const params = [userId];
        const rows: any = await DatabaseUtils.execSql(sql, params);
        // 有且只有一条数据
        return rows.length === 0 ? null : rows[0];
    }

    /**
     * 查询房间信息
     * @param roomId
     * @returns {Promise<void>}
     */
    static getRoomData = async (roomId: string) => {
        const sql = `
            select a.id as id,
                 a.user_id as userId,
                 b.user_name as userName,
                 a.user_page as userPage,
                 a.room_id as roomId,
                 a.room_status as roomStatus,
                 a.is_ready as isReady,
                 a.battle_id as battleId,
                 a.user_status as userStatus,
                 b.score as score,
                 a.first as first,
                 b.pk_total_count as pkTotalCount,
                 b.pk_offline_count as pkOfflineCount,
                 b.pk_win_count as pkWinCount,
                 b.icon_url as iconUrl,
                 a.lock_pass as lockPass,
                 a.is_room_admin as isRoomAdmin,
                 IF(a.disconnect_time IS NOT NULL, 'Y', 'N') as isOffline
                 from t_user_state a
            left join t_user b on a.user_id = b.user_id
            where a.room_id = ?
            and (user_status is null or user_status <> ?)
          `;
        const params = [roomId, USER_STATUS.WATCH];
        const userRows: any = await DatabaseUtils.execSql(sql, params);
        // 处理下图片的地址
        userRows.forEach((user: any) => {
            user.iconUrl = fileUtils.getShowPath(user.iconUrl);
            user.isOffline = BOOLEAN.SHORT_YES === user.isOffline;
        });
        return userRows;
    };

    /**
     * 创建游离数据
     * @param userId
     * @param token
     */
    static createUserState = async (userId: string, token: string) => {
        const sql = `insert into t_user_state(user_id, user_page, token) values(?, ?, ?)`;
        const params = [userId, PAGE_STATUS.PLATFORM, token];
        await DatabaseUtils.execSql(sql, params);
        return true;
    };
}

export default UserStateDao;